package com.lazyframework.security.web.configuration;

import com.lazyframework.security.web.JwtClients;
import com.lazyframework.security.web.authentication.UserDetailsService;
import com.lazyframework.security.web.configuration.configurer.FilterSecurityInterceptorConfigurer;
import com.lazyframework.security.web.configuration.properties.AuthorizeProperties;
import com.lazyframework.security.web.util.PasswordEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;

import javax.servlet.Filter;

public abstract class WebSecurityConfigurerAdapter implements WebSecurityConfigurer<WebSecurity> {

    private boolean disableDefaultConfigure;

    private JwtClients jwtClients;

    private ApplicationContext context;

    private PasswordEncoder passwordEncoder;

    private UserDetailsService userDetailsService;

    private AuthorizeProperties authorizeProperties;

    public WebSecurityConfigurerAdapter() {
        this(false);
    }

    public WebSecurityConfigurerAdapter(boolean disableDefaultConfigure) {
        this.disableDefaultConfigure = disableDefaultConfigure;
    }

    @Override
    public void init(WebSecurity webSecurity) {
        HttpSecurity httpSecurity = getHttp();
        webSecurity.setSecurityBuilder(httpSecurity);
    }

    @Override
    public void configure(WebSecurity webSecurity) {
    }

    /**
     * 派生类自定义配置
     *
     * @param http
     */
    protected void configure(HttpSecurity http) {
    }

    /**
     * 构建HttpSecurity
     *
     * @return
     */
    protected HttpSecurity getHttp() {
        HttpSecurity http = new HttpSecurity();

        // 基础配置
        this.httpBasic(http);

        // 可选配置
        if (!disableDefaultConfigure) {
            // 表单登录(用户名+密码认证)
            http.formLogin()
                    .jwtClients(jwtClients())
                    .passwordEncoder(passwordEncoder)
                    .userDetailsService(userDetailsService());
        }

        // 调用自定义配置
        configure(http);

        // 允许子类自定义受保护的资源
        boolean hasAuthorizeRequestsConfig = false;
        for (SecurityConfigurer<Filter, HttpSecurity> configure : http.getConfigurers()) {
            if (configure.getClass().isAssignableFrom(FilterSecurityInterceptorConfigurer.class)) {
                hasAuthorizeRequestsConfig = true;
                break;
            }
        }

        if (!hasAuthorizeRequestsConfig) {
            http.authorizeRequests()
                    .permissions(authorizeProperties.permissions())
                    .authenticated(authorizeProperties.authenticated());
        }

        return http;
    }

    protected JwtClients jwtClients() {
        return this.jwtClients;
    }

    protected UserDetailsService userDetailsService() {
        return this.userDetailsService;
    }

    @Autowired
    public void setContext(ApplicationContext context) {
        this.context = context;
    }

    @Autowired
    public void setJwtClients(JwtClients jwtClients) {
        this.jwtClients = jwtClients;
    }

    @Autowired
    public void setAuthorizeProperties(AuthorizeProperties authorizeProperties) {
        this.authorizeProperties = authorizeProperties;
    }

    @Autowired
    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Autowired
    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

    /**
     * ===================================== Private Methods =========================================
     */

    private void httpBasic(HttpSecurity http) {
        // JWT认证
        http.jwt()
                .jwtClients(jwtClients())
                .userDetailsService(userDetailsService());
        // 跨域
        http.cors()
                .corsConfigurationSource(this.context.getBean(HandlerMappingIntrospector.class));
    }
}
